package com.fast.common.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Description:
 * @author: HMY 2013-11-24
 * @version V1.0
 */
public class BeanUtils {

	private static Logger logger = LoggerFactory.getLogger(BeanUtils.class);

	public static List<Map<String, Object>> toListMap(List<?> objs) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		if (objs == null) {
			return null;
		}
		try {
			if (objs.size() > 0) {
				for (Object obj : objs) {
					list.add(toMap(obj));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}

	public static Map<String, Object> toFlatMap(Object obj) {
		try {
			return toNewMap(obj);
		} catch (Exception e) {
			logger.error("", e);
		}
		return new HashMap<String, Object>();
	}

	
	public static Map<String, Object> toNewMap(Object obj) throws Exception {
		Map<String, Object> ret = new HashMap<String, Object>();
		if (obj == null) {
			return ret;
		}
		Class<?> clazz = obj.getClass();
		Method[] fields = clazz.getDeclaredMethods();
		
		int len = 0;
		if (fields != null && (len = fields.length) > 0) {
			for (int index = 0; index < len; index++) {
				Method mod = fields[index];
				String methodname = mod.getName();
				if (methodname == null) {
					continue;
				}
				boolean isget = methodname.startsWith("get");
				boolean isBool = methodname.startsWith("is");
				if( !isget &&  !isBool){
					continue;
				}
				//只有get或者is的开头的方法才能进入下面的逻辑
				Object objVal = mod.invoke(obj);
				String typname = mod.getReturnType().getName();
				if (Boolean.class.getName().equals(typname)) {
					objVal = false;
				}
				String fieldname = methodname.substring(3,4).toLowerCase()+methodname.substring(4);
				ret.put(fieldname, objVal != null ? objVal : null);

			}
		}
		return ret;
	}
	
	
	
	
	public static Map<String, Object> toMap(Object obj) throws Exception {
		Map<String, Object> ret = new HashMap<String, Object>();
		if (obj == null) {
			return ret;
		}
		Class<?> clazz = obj.getClass();
		Field[] fields = clazz.getDeclaredFields();
		int len = 0;
		if (fields != null && (len = fields.length) > 0) {
			for (int index = 0; index < len; index++) {
				Field field = fields[index];
				String fieldname = field.getName();
				if (fieldname == null) {
					continue;
				}
				String methodname = fieldname.substring(0, 1).toUpperCase() + fieldname.substring(1);
				methodname = "get" + methodname;
				Method mod = null;
				try {
					mod = clazz.getMethod(methodname);
				} catch (NoSuchMethodException e) {
					logger.error("不支持的方法，忽略处理", e.getMessage());
				}
				if (mod == null) {
					continue;
				}
				Object objVal = mod.invoke(obj);
				String typname = field.getType().getName();
				if (Boolean.class.getName().equals(typname)) {
					objVal = false;
				}
				ret.put(fieldname, objVal != null ? objVal : null);

			}
		}
		return ret;
	}

	/**
	 * @author HMY
	 * @TODO 将bean转换为map 2013-11-30
	 * @param obj
	 * @return
	 * @throws Exception
	 */
	// public static Map<String, Object> toMap(Object obj) throws Exception {
	// Map<String, Object> map = new HashMap<String, Object>();
	// if (obj == null) {
	// return map;
	// }
	// Class<?> clazz = obj.getClass();
	// Method[] mods = clazz.getDeclaredMethods();
	// if (mods != null && mods.length > 0) {
	// for (Method mod : mods) {
	// if (mod != null) {
	// String modname = mod.getName();
	// if (modname != null && modname.startsWith("get") && modname.length() > 4)
	// {
	// String fieldname = null;
	// Object objVal = null;
	// fieldname = modname.substring(3, 4).toLowerCase() + modname.substring(4);
	// objVal = mod.invoke(obj);
	// if (fieldname != null) {
	// map.put(fieldname, objVal != null ? objVal.toString() : null);
	// }
	// }
	// }
	// }
	// }
	// return map;
	// }

	public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz) {
		if (map == null || clazz == null) {
			return null;
		}
		T obj = null;
		try {
			obj = toBean(map, clazz);
		} catch (InstantiationException e) {
			logger.error("error:", e);
		} catch (IllegalAccessException e) {
			logger.error("error:", e);
		} catch (IllegalArgumentException e) {
			logger.error("error:", e);
		} catch (InvocationTargetException e) {
			logger.error("error:", e);
		} catch (SecurityException e) {
			logger.error("error:", e);
		}
		return obj;
	}

	public static <T> T toBean(Map<String, Object> map, Class<T> clazz) throws InstantiationException,
			IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException {
		if (map == null || clazz == null) {
			return null;
		}
		T obj = clazz.newInstance();
		for (Entry<String, Object> entry : map.entrySet()) {
			String keyObj = entry.getKey();
			Object val = entry.getValue();
			if (keyObj != null && keyObj.length() > 1) {
				String methodname = "set" + keyObj.substring(0, 1).toUpperCase() + keyObj.substring(1);
				Field f = null;
				try {
					f = clazz.getDeclaredField(keyObj);
				} catch (NoSuchFieldException e) {
				}
				if (f != null) {
					Class<?> typClazz = f.getType();
					try {
						Method method = clazz.getDeclaredMethod(methodname, typClazz);
						setProperty(typClazz, method, obj, val);
					} catch (NoSuchMethodException e) {
					}

				}
			}
		}
		return obj;
	}

	public static void setProperty(Class<?> typ, Method method, Object obj, Object val)
			throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		logger.info("clazz:{} , value:{}", typ, val);
		if (typ == null) {
			return;
		}
		String tmpVal = null;
		if (val != null) {
			tmpVal = val.toString();
		}
		String typNme = typ.getName();
		if (Short.class.getName().equals(typNme)) {
			method.invoke(obj, NumberUtils.toShort(tmpVal));
		} else if (Integer.class.getName().equals(typNme)) {
			method.invoke(obj, NumberUtils.toInt(tmpVal));
		} else if (Long.class.getName().equals(typNme)) {
			method.invoke(obj, NumberUtils.toLong(tmpVal));
		} else if (Float.class.getName().equals(typNme)) {
			method.invoke(obj, NumberUtils.toFloat(tmpVal));
		} else if (Double.class.getName().equals(typNme)) {
			method.invoke(obj, NumberUtils.toDouble(tmpVal));
		} else if (BigDecimal.class.getName().equals(typNme)) {
			method.invoke(obj, NumberUtils.createBigDecimal(tmpVal));
		} else {
			method.invoke(obj, val.toString());
		}
	}

	/**
	 * @author HMY
	 * @TODO 将map类型转换为相应的对象 2013-11-30
	 * @param map
	 * @param obj
	 * @return
	 * @throws Exception
	 */
	public static Object mapToBean(Map<String, Object> map, Object obj) throws Exception {
		if (map == null || obj == null) {
			return null;
		}
		Class<?> clazz = obj.getClass();
		for (Entry<String, Object> entry : map.entrySet()) {
			String keyObj = entry.getKey();
			Object val = entry.getValue();
			if (keyObj != null && keyObj.length() > 1) {
				String methodname = "set" + keyObj.substring(0, 1).toUpperCase() + keyObj.substring(1);
				Method methods = clazz.getDeclaredMethod(methodname, String.class);
				methods.invoke(obj, val);
			}
		}
		return obj;
	}
}
